/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.amse.grigory.dchess.view;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.amse.grigory.dchess.kernel.*;
import org.amse.grigory.dchess.player.LocalPlayer;
import org.amse.grigory.dchess.rules.*;

/**
 *
 * @author grigory
 */
public class DChessComponent extends JComponent implements IModelListener {

    private final int DIST = 5;
    // Fields
    private IModel myModel;
    private int myFocusX = -1;
    private int myFocusY = -1;
    private LocalPlayer myWhite,  myBlack;
    //Theme fields    
    private Theme myTheme;
    // Constructors

    public DChessComponent(IModel model, LocalPlayer pw, LocalPlayer pb) {
        addMouseListener(new DChessMouse());
        myModel = model;
        myModel.addListener(this);
        myWhite = pw;
        myBlack = pb;
        myTheme = new Theme();
    }
    // Methods

    public void setWhitePlayer(LocalPlayer pw) {
        myWhite = pw;
    }

    public void setBlackPlayer(LocalPlayer pb) {
        myBlack = pb;
    }

    // Getters&Setters
    public Theme getTheme() {
        return myTheme;
    }

    public void setTheme(Theme theme) {
        myTheme = theme;
    }

    public IModel getModel() {
        return myModel;
    }

    public LocalPlayer getWhitePlayer() {
        return myWhite;
    }

    public LocalPlayer getBlackPlayer() {
        return myBlack;
    }

    //Methods to paint
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (myModel.getHeight() == 0) {
            return;
        }
        drawBoard(g);

    }

    private void drawBoard(Graphics g) {
        int width = getWidth() - 15;
        int height = getHeight() - 15;
        int w = myModel.getWidth();
        int h = myModel.getHeight();
        int hx = (int) Math.floor(width / w) + 1;
        int hy = (int) Math.floor(height / h) + 1;
        int maxy = hy * h - hy;
        // Draw Field
        int length = myTheme.getColorsLength();
        for (int k = 0; k < length; ++k) {
            g.setColor(myTheme.getColor(k));
            int x = 0;
            for (int i = 0; i < w; ++i) {
                int y = maxy;
                for (int j = 0; j < h; ++j) {
                    if ((i + j + (h / 4)) % length == k) {
                        g.fillRect(x + DIST, y + DIST, hx, hy);
                    }
                    y -= hy;
                }
                x += hx;
            }
        }
        length = myModel.getIllegalSquareNumber();
        g.setColor(myTheme.getIllegalColor());
        for (int i = 0; i < length; i++) {
            int x = myModel.getIllegalX(i) * hx;
            int y = maxy - myModel.getIllegalY(i) * hy;
            g.fillRect(x + DIST, y + DIST, hx, hy);
        }

        drawFocus(g);
        // Draw Figures
        drawFigures(g);
    }

    private void drawFocus(Graphics g) {
        int width = getWidth() - 15;
        int height = getHeight() - 15;
        int w = myModel.getWidth();
        int h = myModel.getHeight();
        int hx = (int) Math.floor(width / w) + 1;
        int hy = (int) Math.floor(height / h) + 1;
        int maxy = hy * h - hy;
        //Last Move
        Move move = myModel.getMoveCoordinates(myModel.getCurrentMoveNumber());

        if (move != null) {
            int sx, sy, ex, ey;
            sx = move.getSX() - 1;
            sy = move.getSY() - 1;
            ex = move.getEX() - 1;
            ey = move.getEY() - 1;
            g.setColor(myTheme.getIndicationColor());
            g.drawLine(sx * hx + DIST + hx / 2, maxy - sy * hy + DIST + hy / 2, ex * hx + DIST + hx / 2, maxy - ey * hy + DIST + hy / 2);
            g.fillOval(sx * hx + DIST, maxy - sy * hy + DIST, hx, hy);
            g.fillOval(ex * hx + DIST, maxy - ey * hy + DIST, hx, hy);
        }

        //Focus
        if ((myFocusX > -1) && (myFocusY > -1) && (myFocusY < h) && (myFocusX < w)) {
            int x = myFocusX;
            int y = myFocusY;
            if (myModel.getColor() != myModel.getFigureColor(x, y)) {
                return;
            }
            if (myModel.getFigureName(x, y) != null) {
                g.setColor(myTheme.getFigureColor());
                g.fillOval(x * hx + DIST, maxy - y * hy + DIST, hx, hy);

            }
            for (int i = 0; i < w; ++i) {
                for (int j = 0; j < h; ++j) {
                    if (myModel.canMove(x + 1, y + 1, i + 1, j + 1)) {
                        if (myModel.getFigureName(i, j) == null) {
                            g.setColor(myTheme.getMoveColor());
                        } else {
                            g.setColor(myTheme.getAttackColor());
                        }
                        g.fillOval(i * hx + DIST, maxy - j * hy + DIST, hx, hy);
                    }
                }
            }


        }

    }

    private void drawFigures(Graphics g) {
        int width = getWidth() - 15;
        int height = getHeight() - 15;
        int w = myModel.getWidth();
        int h = myModel.getHeight();
        int hx = (int) Math.floor(width / w) + 1;
        int hy = (int) Math.floor(height / h) + 1;
        int maxy = hy * h - hy;
        int x = 0;
        for (int i = 0; i < w; ++i) {
            int y = maxy;
            for (int j = 0; j < h; ++j) {
                String key = myModel.getFigureName(i, j);
                if (key != null) {
                    int color = myModel.getFigureColor(i, j);
                    Image img = null;
                    if (color == 1) {
                        img = myTheme.getWhiteImg(key);
                    }
                    if (color == -1) {
                        img = myTheme.getBlackImg(key);
                    }
                    g.drawImage(img, x + DIST, y + DIST, hx, hy, this);

                }
                y -= hy;
            }
            x += hx;
        }

    }

    //Mouse
    private class DChessMouse extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            if (myModel.isWin() != Rules.NOBODY_WIN) {
                return;
            }
            if (myModel.isPaused()) {
                myFocusX = -1;
                myFocusY = -1;
                return;
            }
            LocalPlayer player = null;
            if ((myModel.getColor() == Rules.COLOR_WHITE)) {
                player = myWhite;
            } else {
                player = myBlack;
            }
            if (player == null) {
                return;
            }

            int width = getWidth() - 15;
            int height = getHeight() - 15;
            int w = myModel.getWidth();
            int h = myModel.getHeight();
            int hx = (int) Math.floor(width / w) + 1;
            int hy = (int) Math.floor(height / h) + 1;
            int x = (e.getX() / hx);
            int y = h - 1 - (e.getY() / hy);
            if (myModel.canMove(myFocusX + 1, myFocusY + 1, x + 1, y + 1)) {
                player.setSX(myFocusX + 1);
                player.setSY(myFocusY + 1);
                player.setX(x + 1);
                player.setY(y + 1);
                myFocusX = -1;
                myFocusY = -1;
                synchronized (player.lock()) {
                    player.move();
                    player.lock().notifyAll();
                }

            } else {
                myFocusX = x;
                myFocusY = y;
            }
            repaint();

        }
    }

    public void update() {
        myFocusX = -1;
        myFocusY = -1;
        repaint();
    }
}
